using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Polymod
{
    public class InvokerRegistry : IEnumerable<IInvoker>, ICloneable
    {
        private Dictionary<string, IInvoker> _invokers = new Dictionary<string, IInvoker>();

        public object GetValue(IModel target, string name)
        {
            if (name == null) throw new System.ArgumentNullException("name");
            IInvoker invoker;
            if (!_invokers.TryGetValue(name, out invoker)) throw new KeyNotFoundException();
            return invoker.GetValue(target);
        }
        public void SetValue(IModel target, string name, object value)
        {
            if (name == null) throw new System.ArgumentNullException("name");
            IInvoker invoker;
            if (!_invokers.TryGetValue(name, out invoker)) throw new KeyNotFoundException();
            invoker.SetValue(target, value);
        }
        public void SetInvoker(string name, IInvoker invoker)
        {
            if (invoker == null) throw new System.ArgumentNullException("invoker");
            if (name == null) throw new System.ArgumentNullException("name");
            _invokers[name] = invoker;
        }
        public IInvoker GetInvoker(string name)
        {
            if (name == null) throw new System.ArgumentNullException("name");
            IInvoker invoker;
            if (!_invokers.TryGetValue(name, out invoker)) throw new KeyNotFoundException();
            return invoker;
        }
        public string[] GetInvokerNames()
        {
            return _invokers.Keys.ToArray();
        }
        public InvokerRegistry Clone()
        {
            //NOTE: It is important to clone the invokers... they may have state data.
            var _tmpClone = _invokers.ToDictionary(kp => kp.Key, kp => kp.Value.Clone());
            var result = new InvokerRegistry();
            result._invokers = _tmpClone;
            return result;
        }

        public IEnumerator<IInvoker> GetEnumerator()
        {
            return _invokers.Values.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        object ICloneable.Clone()
        {
            return this.Clone();
        }
    }
}
